﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Configuration;
using System.Net;
using System.IO;
using System.Diagnostics;
using Lyon.Utility;

namespace Lyon.Updater
{
    internal partial class MainForm : Form
    {
        private void RunBack(System.Threading.ThreadStart start)
        {
            System.Threading.ThreadPool.QueueUserWorkItem(delegate(object obj)
            {
                start();
            }, null);
        }
        private void RunMain(System.Threading.ThreadStart start)
        {
            this.Invoke(start);
        }

        Arguments _Arguments;
        Configuration _AppConfig;
        List<UpdateItem> _UpdateItemList;

        object UpdateVersion
        {
            get
            {
                if (_AppConfig.AppSettings.Settings["UpdateVersion"] == null)
                    return null;
                return Arguments.Deserialize(_AppConfig.AppSettings.Settings["UpdateVersion"].Value);
            }
            set
            {
                if (_AppConfig.AppSettings.Settings["UpdateVersion"] == null)
                    _AppConfig.AppSettings.Settings.Add("UpdateVersion", Arguments.Serialize(value));
                else
                    _AppConfig.AppSettings.Settings["UpdateVersion"].Value = Arguments.Serialize(value);
                _AppConfig.Save();
            }
        }
        string UpdateUrl
        {
            get
            {
                if (_AppConfig.AppSettings.Settings["UpdateUrl"] == null)
                    return null;
                return _AppConfig.AppSettings.Settings["UpdateUrl"].Value;
            }
            set
            {
                if (_AppConfig.AppSettings.Settings["UpdateUrl"] == null)
                    _AppConfig.AppSettings.Settings.Add("UpdateUrl", value);
                else
                    _AppConfig.AppSettings.Settings["UpdateUrl"].Value = value;
                _AppConfig.Save();
            }
        }

        public MainForm(Arguments arguments)
        {
            _Arguments = arguments;
            _AppConfig = ConfigurationManager.OpenExeConfiguration(_Arguments.AppFileName);

            InitializeComponent();

            this.Text = String.Format("在线升级[{0}]"
                   , String.IsNullOrEmpty(_Arguments.AppMainWindowTitle) ? _Arguments.ProcessName : _Arguments.AppMainWindowTitle);
            this.Icon = AppIcon.GetAppSmallIcon(_Arguments.AppFileName);
        }

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
            CheckUpdate();
        }

        private void BT_Configure_Click(object sender, EventArgs e)
        {
            ConfigureForm dialog = new ConfigureForm();
            if (String.IsNullOrEmpty(UpdateUrl))
                dialog.UpdateUrl = "http://127.0.0.1/UpdateConfig.xml";
            else
                dialog.UpdateUrl = UpdateUrl;
            if (dialog.ShowDialog(this) == System.Windows.Forms.DialogResult.OK)
            {
                if (UpdateUrl != dialog.UpdateUrl)
                {
                    UpdateUrl = dialog.UpdateUrl;
                    CheckUpdate();
                }
            }
        }

        private void Button_Update_Click(object sender, EventArgs e)
        {
            if (_UpdateItemList == null || _UpdateItemList.Count == 0)
                this.Close();
            else
                StartUpdate();
        }

        private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (listBox1.SelectedIndex >= 0)
            {
                UpdateItem item = _UpdateItemList[listBox1.SelectedIndex];
                GB_UpdateItem.Text = String.Format("版本:{0}", item.Version);
                Label_PublishDate.Text = String.Format("发布日期:{0}",item.PublishDate);
                Label_FileSize.Text = String.Format("更新大小:{0}", item.FileSize);
                Label_Content.Text = String.Format("更新内容:{0}", item.Content);
            }
        }

        private void CheckUpdate()
        {
            RunBack(delegate
            {
                RunMain(delegate
                {
                    BT_Configure.Enabled = false;
                    BT_Update.Visible = false;
                    tabControl1.SelectedTab = tabPage1;
                    this.Label_CheckUpdate.Text = String.Format("正在检查新版本({0})……", UpdateUrl);
                });
                try
                {
                    UpdateInfo updateInfo = UpdateInfo.LoadInfo(UpdateUrl, UpdateVersion);
                    _UpdateItemList = new List<UpdateItem>(updateInfo.Installing);
                }
                catch (Exception ex)
                {
                    RunMain(delegate
                    {
                        Label_CheckUpdate.Text = String.Format("检查更新时出错。{0}{1}", Environment.NewLine, ex.Message);
                        BT_Update.Text = "关闭";
                        BT_Update.Visible = true;
                        BT_Configure.Enabled = true;
                    });
                    return;
                }
                RunMain(delegate
                {
                    if (_UpdateItemList.Count == 0)
                    {
                        Label_CheckUpdate.Text = "已经是最新版本了！";
                        BT_Update.Text = "关闭";
                        BT_Update.Visible = true;
                    }
                    else
                    {
                        BT_Update.Text = "更新";
                        BT_Update.Visible = true;

                        listBox1.Items.Clear();
                        _UpdateItemList.ForEach(delegate(UpdateItem item) { listBox1.Items.Add(String.Format("[ ]{0}", item.Version)); });
                        listBox1.SelectedIndex = 0;
                        tabControl1.SelectedTab = tabPage2;
                    }
                    BT_Configure.Enabled = true;
                });
                
            });
        }

        private void StartUpdate()
        {
            RunBack(delegate
            {
                CloseApp();
                RunMain(delegate { BT_Update.Enabled = false; });
                try
                {
                    _UpdateItemList.ForEach(delegate(UpdateItem item)
                    {
                        int i = _UpdateItemList.IndexOf(item);
                        RunMain(delegate { listBox1.SelectedIndex = i; listBox1.Items[i] = String.Format("[-]{0}", item.Version); });
                        Install(item);
                        UpdateVersion = item.Version;
                        RunMain(delegate { listBox1.Items[i] = String.Format("[*]{0}", item.Version); });
                    });

                    StartApp();
                    RunMain(delegate { this.Close(); });
                }
                catch (Exception ex)
                {
                    RunMain(delegate
                    {
                        BT_Update.Enabled = true;
                        MessageBox.Show(this, ex.ToString());
                    });
                }
            });
        }

        private void Install(UpdateItem item)
        {
            string url = String.Format(@"{0}/{1}", UpdateUrl, item.FileName);
            string path = String.Format(@"{0}\{1}", AppDomain.CurrentDomain.BaseDirectory, item.FileName);
            if (File.Exists(path))
                File.Delete(path);
            UpdateInfo.LoadWebFile(url, path);
            Process process = Process.Start(path);
            process.WaitForExit();
            File.Delete(path);
        }
        private void CloseApp()
        {
            try
            {
                Process appProcess = Process.GetProcessById(_Arguments.ProcessID);
                if (appProcess != null && appProcess.ProcessName == _Arguments.ProcessName)
                {
                    appProcess.Kill();
                    appProcess.WaitForExit();
                }
            }
            catch (Exception ex)
            {
            }
            Process[] appProcesses = Process.GetProcessesByName(_Arguments.ProcessName);
            //StringBuilder builder = new StringBuilder("在进行之前请将关闭这些应用程序:");
            //List<Process> list = new List<Process>(appProcesses.Length);
            foreach (Process item in appProcesses)
            {

                if (item.MainModule.FileName == _Arguments.AppFileName)
                {
                    item.Kill();
                    item.WaitForExit();

                    //list.Add(item);
                    //builder.AppendLine();
                    //builder.AppendFormat("{1}({0})", item.Id, item.MainWindowTitle);
                }
            }
            //MessageBox.Show(builder.ToString(), this.Text);
        }
        private void StartApp()
        {
            Process p = Process.Start(_Arguments.AppFileName);
        }
    }
}